import paramiko

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from config import project_dir
from database import get_db
from model.cdn_config import CdnConfig
from model.cdn_node import CdnNode
from pydantic import ConfigDict
import yaml
import subprocess

from route.user_api import get_current_user

router = APIRouter(tags=["api"]
                   , dependencies=[Depends(get_current_user)]  # 🔑 所有路由都需要认证
                   )


def distribute_cert(server: dict, domain: str):
    fullchain_path = f"/etc/letsencrypt/live/{domain}/fullchain.pem"
    privkey_path = f"/etc/letsencrypt/live/{domain}/privkey.pem"
    remote_cert_dir = f"/etc/nginx/ssl/{domain}/"

    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(server["host"], username=server["user"])  # 可以配置 key 或 password

    sftp = ssh.open_sftp()
    try:
        # 确保远程目录存在
        try:
            sftp.stat(remote_cert_dir)
        except FileNotFoundError:
            ssh.exec_command(f"mkdir -p {remote_cert_dir}")

        # 上传证书文件
        sftp.put(fullchain_path, f"{remote_cert_dir}/fullchain.pem")
        sftp.put(privkey_path, f"{remote_cert_dir}/privkey.pem")
    finally:
        sftp.close()

    # 让 nginx 重新加载
    ssh.exec_command("systemctl reload nginx")
    ssh.close()


@router.post("/apply_and_distribute/{cdn_config_id}")
def apply_and_distribute_cert(cdn_config_id: int, db: Session = Depends(get_db)):
    cdn_config = db.query(CdnConfig).filter(CdnConfig.id == cdn_config_id).first()
    if not cdn_config:
        raise HTTPException(status_code=404, detail="CDN 配置不存在")

    domain = cdn_config.domain
    email = "admin@example.com"

    # Step 1: 如果没有证书，则申请
    if not cdn_config.fullchain or not cdn_config.privkey:
        try:
            subprocess.run(
                [
                    "certbot", "certonly", "--standalone",
                    "-d", domain,
                    "--non-interactive",
                    "--agree-tos",
                    "--email", email
                ],
                capture_output=True, text=True, check=True
            )
        except subprocess.CalledProcessError as e:
            raise HTTPException(status_code=500, detail=f"证书申请失败: {e.stderr}")

        # Step 2: 读取证书内容存入数据库
        fullchain_path = f"/etc/letsencrypt/live/{domain}/fullchain.pem"
        privkey_path = f"/etc/letsencrypt/live/{domain}/privkey.pem"
        with open(fullchain_path, "r") as f:
            cdn_config.fullchain = f.read()
        with open(privkey_path, "r") as f:
            cdn_config.privkey = f.read()
        cdn_config.ifDeploy = True
        db.commit()

    # Step 3: 分发到所有可用节点
    nodes = db.query(CdnNode).filter(CdnNode.status == True).all()
    errors = []
    for node in nodes:
        try:
            distribute_cert(node, domain)
        except Exception as e:
            errors.append(f"{node.host}: {str(e)}")

    result = {"status": "success", "message": f"{domain} 证书已分发到节点"}
    if errors:
        result["errors"] = errors

    return result
